Template file

Author
Affiliation

Magnus Johansson

Published

2024-06-25

Code
# one package below requires that you use devtools to install them manually:
# first install devtools by
# install.packages('devtools')

library(RISEkbmRasch) # devtools::install_github("pgmj/RISEkbmRasch")
library(grateful)
library(ggrepel)
library(car)
library(kableExtra)
library(readxl)
library(tidyverse)
library(eRm)
library(mirt)
library(psych)
library(psychotree)
library(matrixStats)
library(reshape)
library(knitr)
library(patchwork)
library(formattable) 
library(glue)

### optional libraries
#library(TAM)
#library(skimr)
#library(janitor)

### some commands exist in multiple packages, here we define preferred ones that are frequently used
select <- dplyr::select
count <- dplyr::count
recode <- car::recode
rename <- dplyr::rename

Our data comes from an open dataset (Echeverría et al., n.d.) connected to a paper validating the Spanish version of the Mental Health Continuum-Short Form Questionnaire [MHC-SF; Echeverría et al. (2017)].

Code
### import data - this is just sample code, the files do not exist
library(readxl) # for reading excel files
df.all <- read_excel("data/data_sMHCSF_Echeverria2017.xlsx")
df <- df.all
### create dif variables
dif.sex <- factor(df$Sex)
df$Sex <- NULL
# check levels with 
#levels(dif.sex)

### label gender variable as factor
# dif.gender <- factor(dif.gender,
#                       levels = c(1,2,3),
#                       labels = c("Female", "Male", "Other/missing response"))

### Load item information
# make sure that variable names in df match with itemlabels$itemnr
itemlabels <- read_excel("data/itemlabels_MHC_SF.xlsx") %>% 
  mutate(item = str_squish(item))

# match df variable names to itemlabels$itemnr variable
names(df) <- itemlabels$itemnr

# recode response categories to numbers
df <- df %>%
  mutate(across(everything(), ~ car::recode(.x,"'Never'=0;'1 or 2 times a month'=1;'About 1 time a week'=2;'About 2 or 3 times a week'=3;'Almost daily'=4;'Daily'=5", as.factor = FALSE)))
Code
##### Optionally: filter participants based on missing data

##### Before filtering out participants, you should check the missing data structure using RImissing() and RImissingP()

# If you want to include participants with missing data, input the minimum number of items responses that a participant should have to be included in the analysis:
# min.responses <- 3
# 
# # Select the variables we will work with, and filter out respondents with a lot of missing data
# df <- df %>% 
#   select(starts_with("item"),Sex,Age) %>%  # variables that start with "item", and DIF-variables Sex and Age
#   filter(length(itemlabels$itemnr)-rowSums(is.na(.[itemlabels$itemnr])) >= min.responses) # include only respondents with data for at least 3 items
# 
# #---- OR just filter out all respondents with any missing data----
# df <- df %>% 
#   select(starts_with("WAAQ"),Sex,Age) %>% 
#   #mutate(across(where(is.character), ~ as.numeric(.x))) %>% # if data is input as characters, we need to convert to numeric
#   na.omit()
Code
# optionally, load RISE ggplot theme and color palettes and set the theme as default.
# just comment out the row below if you desire different theming
source("RISE_theme.R")

1 All items in the analysis

Code
itemnr item
mhc1 Happy
mhc2 Interested in life
mhc3 Satisfied with your life
mhc4 That you had something important to contribute to society?
mhc5 That you belonged to a community?
mhc6 That our society is becoming a better place for people like you?
mhc7 That people are basically good?
mhc8 That the way our society works makes sense to you?
mhc9 That you liked most parts of your personality?
mhc10 Good at managing the responsibilities of your daily life?
mhc11 That you had warm and trusting relationships with others?
mhc12 That you had experiences that challenged you to grow and become a better person?
mhc13 Confident to think or express your own ideas and opinions?
mhc14 That your life has a sense of direction or meaning to it?

2 Demographics

Code
RIdemographics(dif.sex, "Gender")
Gender n Percent
Man 962 28.7
Woman 2393 71.3

2.1 Descriptives of raw data

Response distribution for all items are summarized below.

Code
Response category Number of responses Percent
0 4439 9.5
1 5742 12.2
2 5053 10.8
3 7895 16.8
4 13076 27.8
5 10765 22.9

2.2 Descriptives - item level

Code
RIlistItemsMargin(df, fontsize = 12)
itemnr item
mhc1 Happy
mhc2 Interested in life
mhc3 Satisfied with your life
mhc4 That you had something important to contribute to society?
mhc5 That you belonged to a community?
mhc6 That our society is becoming a better place for people like you?
mhc7 That people are basically good?
mhc8 That the way our society works makes sense to you?
mhc9 That you liked most parts of your personality?
mhc10 Good at managing the responsibilities of your daily life?
mhc11 That you had warm and trusting relationships with others?
mhc12 That you had experiences that challenged you to grow and become a better person?
mhc13 Confident to think or express your own ideas and opinions?
mhc14 That your life has a sense of direction or meaning to it?

3 Rasch analysis 1

The eRm package, which uses Conditional Maximum Likelihood (CML) estimation, will be used primarily. For this analysis, the Partial Credit Model will be used.

itemnr item
mhc1 Happy
mhc2 Interested in life
mhc3 Satisfied with your life
mhc4 That you had something important to contribute to society?
mhc5 That you belonged to a community?
mhc6 That our society is becoming a better place for people like you?
mhc7 That people are basically good?
mhc8 That the way our society works makes sense to you?
mhc9 That you liked most parts of your personality?
mhc10 Good at managing the responsibilities of your daily life?
mhc11 That you had warm and trusting relationships with others?
mhc12 That you had experiences that challenged you to grow and become a better person?
mhc13 Confident to think or express your own ideas and opinions?
mhc14 That your life has a sense of direction or meaning to it?
Code
RIitemfitPCM2(df,samplesize = 250,nsamples = 4)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
mhc1 0.894 0.889 -1.103 -1.364
mhc2 0.723 0.788 -3.081 -2.462
mhc3 0.784 0.802 -1.963 -2.858
mhc4 1.086 1.059 0.674 0.593
mhc5 1.612 1.44 2.757 4.532
mhc6 0.951 0.952 0.254 -0.673
mhc7 1.153 1.138 1.796 1.831
mhc8 1.096 1.089 1.036 1.262
mhc9 0.815 0.815 -2.361 -2.876
mhc10 0.899 0.913 -0.601 -1.706
mhc11 0.806 0.818 -2.179 -1.971
mhc12 0.821 0.822 -1.95 -0.985
mhc13 0.921 0.934 -0.809 -0.364
mhc14 0.671 0.707 -2.723 -3.232
Code

PCA of Rasch model residuals

Eigenvalues
2.51
1.67
1.40
1.15
1.02
Code
RIresidcorr(df, cutoff = 0.2)
mhc1 mhc2 mhc3 mhc4 mhc5 mhc6 mhc7 mhc8 mhc9 mhc10 mhc11 mhc12 mhc13 mhc14
mhc1
mhc2 0.2
mhc3 0.27 0.3
mhc4 -0.13 -0.07 -0.13
mhc5 -0.14 -0.14 -0.2 0.07
mhc6 -0.17 -0.13 -0.17 -0.02 0.04
mhc7 -0.13 -0.13 -0.15 -0.14 -0.05 0.22
mhc8 -0.17 -0.14 -0.13 -0.14 -0.1 0.34 0.3
mhc9 -0.03 -0.09 -0.09 -0.13 -0.23 -0.23 -0.17 -0.18
mhc10 -0.07 -0.1 0 -0.14 -0.26 -0.22 -0.19 -0.15 0.15
mhc11 0 -0.1 -0.08 -0.19 -0.09 -0.23 -0.13 -0.21 0.06 0.07
mhc12 -0.04 -0.11 -0.11 -0.03 -0.17 -0.21 -0.23 -0.23 0.04 0.01 0.17
mhc13 -0.1 -0.12 -0.14 -0.14 -0.2 -0.27 -0.22 -0.26 0.24 0.11 0.09 0.12
mhc14 -0.06 0.08 0.06 -0.06 -0.22 -0.24 -0.28 -0.21 0.02 0.09 0 0.09 0.15
Note:
Relative cut-off value (highlighted in red) is 0.132, which is 0.2 above the average correlation.
Code

Code
mirt(df, model=1, itemtype='Rasch', verbose = FALSE) %>% 
  plot(type="trace", as.table = TRUE, 
       theta_lim = c(-6,6))

Code

Code
# increase fig-height above as needed, if you have many items
RItargeting(df,bins = 50)

Code

mhc5 is high in item fit, and also deviant in loadings on 1st residual contrast.

PCA eigenvalue is above 2, there clearly is multidimensionality.

Two clusters in residual correlations:

  • items 1-3
  • items 6-8

Response category thresholds are disordered for many items.

  • ‘Never’=0;
  • ‘1 or 2 times a month’=1;
  • ‘About 1 time a week’=2;
  • ‘About 2 or 3 times a week’=3;
  • ‘Almost daily’=4;
  • ‘Daily’=5
Code
df %>% 
  mutate(across(everything(), ~ recode(.x, "3=2;4=3;5=4"))) %>% 
  RItileplot()

Code
df.backup <- df

df <- df %>% 
  mutate(across(everything(), ~ recode(.x, "3=2;4=3;5=4")))

3.1 ICC check after recode

Code
mirt(df, model=1, itemtype='Rasch', verbose = FALSE) %>% 
  plot(type="trace", as.table = TRUE, 
       theta_lim = c(-6,6))

Code
removed.items <- c("mhc5")

#df$mhc5 <- NULL

df <- df %>% 
  select(!any_of(removed.items))

4 Rasch 2

We removed item mhc5 due to high item fit and deviant 1st contrast loadings.

Response category 2 and 3 were merged, this is now “1-3 times a week”.

itemnr item
mhc1 Happy
mhc2 Interested in life
mhc3 Satisfied with your life
mhc4 That you had something important to contribute to society?
mhc6 That our society is becoming a better place for people like you?
mhc7 That people are basically good?
mhc8 That the way our society works makes sense to you?
mhc9 That you liked most parts of your personality?
mhc10 Good at managing the responsibilities of your daily life?
mhc11 That you had warm and trusting relationships with others?
mhc12 That you had experiences that challenged you to grow and become a better person?
mhc13 Confident to think or express your own ideas and opinions?
mhc14 That your life has a sense of direction or meaning to it?
Code
RIitemfitPCM2(df,samplesize = 250,nsamples = 4)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
mhc1 0.889 0.888 -1.406 -1.238
mhc2 0.767 0.812 -2.349 -1.972
mhc3 0.796 0.801 -2.459 -2.591
mhc4 1.155 1.14 2.394 1.108
mhc6 1.063 1.071 1.021 2.065
mhc7 1.184 1.177 1.612 1.348
mhc8 1.157 1.149 1.302 1.885
mhc9 0.834 0.824 -1.653 -2.206
mhc10 0.9 0.909 -1.091 -1.666
mhc11 0.847 0.843 -2.313 -1.443
mhc12 0.839 0.834 -1.964 -2.202
mhc13 0.94 0.941 -0.505 -0.921
mhc14 0.682 0.705 -3.237 -3.622
Code

PCA of Rasch model residuals

Eigenvalues
2.42
1.68
1.25
1.15
1.01
Code
RIresidcorr(df, cutoff = 0.2)
mhc1 mhc2 mhc3 mhc4 mhc6 mhc7 mhc8 mhc9 mhc10 mhc11 mhc12 mhc13 mhc14
mhc1
mhc2 0.15
mhc3 0.23 0.25
mhc4 -0.13 -0.08 -0.14
mhc6 -0.17 -0.14 -0.18 0.03
mhc7 -0.13 -0.14 -0.17 -0.12 0.24
mhc8 -0.18 -0.16 -0.16 -0.11 0.35 0.27
mhc9 -0.04 -0.12 -0.1 -0.14 -0.24 -0.19 -0.2
mhc10 -0.1 -0.11 -0.03 -0.17 -0.23 -0.21 -0.18 0.09
mhc11 -0.01 -0.1 -0.09 -0.17 -0.24 -0.13 -0.23 0.03 0.03
mhc12 -0.05 -0.12 -0.12 -0.04 -0.22 -0.24 -0.25 0 -0.02 0.16
mhc13 -0.12 -0.13 -0.16 -0.15 -0.29 -0.22 -0.28 0.2 0.09 0.06 0.08
mhc14 -0.06 0.05 0.05 -0.06 -0.26 -0.29 -0.24 -0.01 0.05 -0.02 0.05 0.09
Note:
Relative cut-off value (highlighted in red) is 0.125, which is 0.2 above the average correlation.
Code

Code
mirt(df, model=1, itemtype='Rasch', verbose = FALSE) %>% 
  plot(type="trace", as.table = TRUE, 
       theta_lim = c(-6,6))

Code

Code
# increase fig-height above as needed, if you have many items
RItargeting(df,bins = 50)

Code

We still have two clusters of residual correlations.

  • Items 1-3
  • 6-8

It looks like item 1 has the best targeting and item fit, we remove 2 and 3.

Item 7 has better distance between response categories, we remove 6 and 8.

Code
removed.items <- c("mhc5","mhc2","mhc3","mhc6","mhc8")

#df$mhc5 <- NULL

df.backup2 <- df

df <- df %>% 
  select(!any_of(removed.items))

5 Rasch 3

itemnr item
mhc1 Happy
mhc2 Interested in life
mhc3 Satisfied with your life
mhc4 That you had something important to contribute to society?
mhc6 That our society is becoming a better place for people like you?
mhc7 That people are basically good?
mhc8 That the way our society works makes sense to you?
mhc9 That you liked most parts of your personality?
mhc10 Good at managing the responsibilities of your daily life?
mhc11 That you had warm and trusting relationships with others?
mhc12 That you had experiences that challenged you to grow and become a better person?
mhc13 Confident to think or express your own ideas and opinions?
mhc14 That your life has a sense of direction or meaning to it?
Code
RIitemfitPCM2(df,samplesize = 250,nsamples = 4)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
mhc1 0.931 0.933 -0.912 -0.972
mhc4 1.186 1.174 1.245 1.531
mhc7 1.374 1.36 4.734 2.81
mhc9 0.765 0.758 -3.142 -2.189
mhc10 0.865 0.864 -1.26 -1.043
mhc11 0.766 0.775 -2.498 -2.49
mhc12 0.751 0.756 -2.981 -2.673
mhc13 0.814 0.824 -2.097 -2.315
mhc14 0.652 0.687 -3.334 -3.298
Code

PCA of Rasch model residuals

Eigenvalues
1.54
1.28
1.23
1.11
1.06
Code
RIresidcorr(df, cutoff = 0.2)
mhc1 mhc4 mhc7 mhc9 mhc10 mhc11 mhc12 mhc13 mhc14
mhc1
mhc4 -0.13
mhc7 -0.08 -0.07
mhc9 -0.08 -0.21 -0.18
mhc10 -0.13 -0.22 -0.19 0
mhc11 -0.04 -0.24 -0.13 -0.08 -0.07
mhc12 -0.09 -0.11 -0.23 -0.12 -0.13 0.05
mhc13 -0.18 -0.25 -0.24 0.08 -0.03 -0.07 -0.06
mhc14 -0.07 -0.09 -0.24 -0.11 -0.03 -0.11 -0.05 -0.03
Note:
Relative cut-off value (highlighted in red) is 0.09, which is 0.2 above the average correlation.
Code

Code
mirt(df, model=1, itemtype='Rasch', verbose = FALSE) %>% 
  plot(type="trace", as.table = TRUE, 
       theta_lim = c(-6,6))

Code

Code
# increase fig-height above as needed, if you have many items
RItargeting(df,bins = 50)

Code

Item 7 has high item fit and deviant loadings on the 1st residual contrast. We will remove it.

No residual correlations remain.

Code
removed.items <- c("mhc5","mhc2","mhc3","mhc6","mhc8","mhc7")

#df$mhc5 <- NULL

df.backup3 <- df

df <- df %>% 
  select(!any_of(removed.items))

6 Rasch 4

itemnr item
mhc1 Happy
mhc4 That you had something important to contribute to society?
mhc7 That people are basically good?
mhc9 That you liked most parts of your personality?
mhc10 Good at managing the responsibilities of your daily life?
mhc11 That you had warm and trusting relationships with others?
mhc12 That you had experiences that challenged you to grow and become a better person?
mhc13 Confident to think or express your own ideas and opinions?
mhc14 That your life has a sense of direction or meaning to it?
Code
RIitemfitPCM2(df,samplesize = 250,nsamples = 4)
OutfitMSQ InfitMSQ OutfitZSTD InfitZSTD
mhc1 1.011 1.007 0.562 0.709
mhc4 1.312 1.286 3.199 2.605
mhc9 0.802 0.794 -2.645 -2.429
mhc10 0.904 0.903 -1.303 -1.521
mhc11 0.814 0.826 -2.699 -2.494
mhc12 0.771 0.778 -2.87 -2.172
mhc13 0.842 0.848 -1.494 -1.95
mhc14 0.68 0.701 -2.597 -3.173
Code

PCA of Rasch model residuals

Eigenvalues
1.45
1.28
1.18
1.14
1.07
Code
RIresidcorr(df, cutoff = 0.2)
mhc1 mhc4 mhc9 mhc10 mhc11 mhc12 mhc13 mhc14
mhc1
mhc4 -0.14
mhc9 -0.1 -0.23
mhc10 -0.15 -0.25 -0.04
mhc11 -0.06 -0.25 -0.11 -0.1
mhc12 -0.12 -0.13 -0.18 -0.18 0.02
mhc13 -0.21 -0.28 0.04 -0.08 -0.11 -0.12
mhc14 -0.09 -0.12 -0.16 -0.08 -0.16 -0.11 -0.09
Note:
Relative cut-off value (highlighted in red) is 0.072, which is 0.2 above the average correlation.
Code

Code
mirt(df, model=1, itemtype='Rasch', verbose = FALSE) %>% 
  plot(type="trace", as.table = TRUE, 
       theta_lim = c(-6,6))

Code

Code
# increase fig-height above as needed, if you have many items
RItargeting(df,bins = 50)

Code

7 LRT-based DIF

Code
erm.out <- PCM(df)
LRtest(erm.out, splitcr = dif.sex) 

Andersen LR-test: 
LR-value: 70.775 
Chi-square df: 31 
p-value:  0 

Review the documentation for further details, using ?LRtest in your R console panel in Rstudio. There is also a plotting function, plotGOF() that may be of interest.

itemnr item
mhc1 Happy
mhc4 That you had something important to contribute to society?
mhc9 That you liked most parts of your personality?
mhc10 Good at managing the responsibilities of your daily life?
mhc11 That you had warm and trusting relationships with others?
mhc12 That you had experiences that challenged you to grow and become a better person?
mhc13 Confident to think or express your own ideas and opinions?
mhc14 That your life has a sense of direction or meaning to it?
Code
RIdifTableLR(df, dif.sex)
Item locations
Standard errors
Item Man Woman MaxDiff All SE_Man SE_Woman SE_All
mhc1 0.44 0.379 0.061 0.396 0.176 0.105 0.090
mhc4 1.418 1.53 0.112 1.492 0.121 0.076 0.064
mhc9 0.754 0.875 0.121 0.837 0.135 0.083 0.070
mhc10 0.524 0.568 0.044 0.553 0.139 0.086 0.073
mhc11 0.391 0.342 0.049 0.353 0.146 0.091 0.077
mhc12 0.687 0.585 0.102 0.612 0.134 0.084 0.071
mhc13 0.291 0.601 0.31 0.514 0.146 0.084 0.072
mhc14 0.499 0.571 0.072 0.546 0.135 0.082 0.070
Note:
Values highlighted in red are above the chosen cutoff 0.5 logits. Background color brown and blue indicate the lowest and highest values among the DIF groups.
Code
RIdifFigureLR(df, dif.sex)

Code
RIdifThreshTblLR(df, dif.sex)
Threshold locations
Standard errors
Item threshold Man Woman MaxDiff All SE_Man SE_Woman SE_All
mhc1
c1 -2.36 -2.372 0.012 -2.363 0.348 0.193 0.168
c2 -0.916 -1.119 0.203 -1.058 0.137 0.089 0.075
c3 1.469 1.452 0.017 1.455 0.092 0.060 0.050
c4 3.566 3.556 0.01 3.550 0.125 0.078 0.066
mhc4
c1 0.436 0.181 0.255 0.252 0.133 0.081 0.069
c2 0.331 0.499 0.168 0.450 0.121 0.073 0.063
c3 1.797 2.192 0.395 2.069 0.105 0.069 0.057
c4 3.108 3.246 0.138 3.198 0.124 0.083 0.069
mhc9
c1 -1.04 -1.08 0.04 -1.063 0.200 0.113 0.098
c2 -0.293 -0.275 0.018 -0.281 0.128 0.078 0.067
c3 1.25 1.525 0.275 1.440 0.098 0.063 0.053
c4 3.099 3.329 0.23 3.253 0.115 0.076 0.064
mhc10
c1 -1.221 -1.216 0.005 -1.213 0.214 0.127 0.109
c2 -0.346 -0.613 0.267 -0.536 0.132 0.085 0.072
c3 1.15 1.319 0.169 1.267 0.101 0.064 0.054
c4 2.515 2.782 0.267 2.696 0.107 0.071 0.059
mhc11
c1 -1.354 -1.606 0.252 -1.537 0.237 0.145 0.123
c2 -0.585 -0.787 0.202 -0.728 0.140 0.088 0.074
c3 1.1 1.23 0.13 1.190 0.100 0.064 0.054
c4 2.402 2.53 0.128 2.486 0.106 0.069 0.057
mhc12
c1 -0.828 -1.281 0.453 -1.155 0.193 0.121 0.103
c2 -0.4 -0.389 0.011 -0.388 0.130 0.080 0.068
c3 1.486 1.527 0.041 1.512 0.100 0.065 0.055
c4 2.489 2.484 0.005 2.479 0.111 0.071 0.059
mhc13
c1 -1.236 -0.931 0.305 -0.986 0.232 0.117 0.104
c2 -0.566 -0.49 0.076 -0.515 0.144 0.085 0.073
c3 1.01 1.39 0.38 1.275 0.104 0.066 0.055
c4 1.957 2.437 0.48 2.284 0.103 0.070 0.057
mhc14
c1 -0.482 -0.811 0.329 -0.726 0.183 0.105 0.091
c2 -0.218 0.036 0.254 -0.031 0.143 0.083 0.072
c3 0.962 1.191 0.229 1.119 0.110 0.072 0.060
c4 1.735 1.867 0.132 1.822 0.103 0.068 0.057
Note:
Values highlighted in red are above the chosen cutoff 0.5 logits. Background color brown and blue indicate the lowest and highest values among the DIF groups.
Code
RIdifThreshFigLR(df, dif.sex)

8 DIF-analysis 2

8.1 Gender

itemnr item
mhc1 Happy
mhc4 That you had something important to contribute to society?
mhc9 That you liked most parts of your personality?
mhc10 Good at managing the responsibilities of your daily life?
mhc11 That you had warm and trusting relationships with others?
mhc12 That you had experiences that challenged you to grow and become a better person?
mhc13 Confident to think or express your own ideas and opinions?
mhc14 That your life has a sense of direction or meaning to it?
Code
RIdifTable(df, dif.sex)

Item 2 3 Mean location StDev MaxDiff
mhc1 -0.186 -0.302 -0.244 0.082 0.116
mhc4 0.792 0.848 0.820 0.040 0.056
mhc9 0.129 0.193 0.161 0.046 0.065
mhc10 -0.101 -0.113 -0.107 0.009 0.012
mhc11 -0.235 -0.340 -0.287 0.074 0.105
mhc12 0.061 -0.096 -0.017 0.111 0.157
mhc13 -0.335 -0.080 -0.207 0.180 0.255
mhc14 -0.126 -0.111 -0.118 0.011 0.016
Code
RIdifFigure(df, dif.sex)

Code
RIdifFigThresh(df, dif.sex)

8.2 Person location & infit ZSTD

Code
RIpfit(df)

9 Test Information (Reliability)

Code
RItif(df)

10 lordif

Code
library(lordif)

g_dif <- lordif(as.data.frame(df), as.numeric(dif.sex), # make sure that the data is in a dataframe-object and that the DIF variable is numeric
                criterion = c("Chisqr"), 
                alpha = 0.01, 
                beta.change = 0.1,
                model = "GPCM",
                R2.change = 0.02)

g_dif_sum <- summary(g_dif)
Code
# threshold values for colorizing the table below
alpha = 0.01
beta.change = 0.1
R2.change = 0.02

g_dif_sum$stats %>% 
  as.data.frame() %>% 
  select(!all_of(c("item","df12","df13","df23"))) %>% 
  round(3) %>% 
  add_column(itemnr = names(df), .before = "ncat") %>% 
  mutate(across(c(chi12,chi13,chi23), ~ cell_spec(.x,
                               color = case_when(
                                 .x < alpha ~ "red",
                                 TRUE ~ "black"
                               )))) %>%
  mutate(across(starts_with("pseudo"), ~ cell_spec(.x,
                               color = case_when(
                                 .x > R2.change ~ "red",
                                 TRUE ~ "black"
                               )))) %>%
  mutate(beta12 =  cell_spec(beta12,
                               color = case_when(
                                 beta12 > beta.change ~ "red",
                                 TRUE ~ "black"
                               ))) %>% 
  kbl_rise()
itemnr ncat chi12 chi13 chi23 beta12 pseudo12.McFadden pseudo13.McFadden pseudo23.McFadden pseudo12.Nagelkerke pseudo13.Nagelkerke pseudo23.Nagelkerke pseudo12.CoxSnell pseudo13.CoxSnell pseudo23.CoxSnell
mhc1 5 0.003 0.01 0.665 0.005 0.001 0.001 0 0.002 0.002 0 0.001 0.002 0
mhc4 5 0.175 0.358 0.644 0.001 0 0 0 0 0 0 0 0 0
mhc9 5 0.292 0.399 0.393 0 0 0 0 0 0 0 0 0 0
mhc10 5 0.751 0.899 0.737 0 0 0 0 0 0 0 0 0 0
mhc11 5 0.073 0.107 0.265 0.002 0 0 0 0 0 0 0 0 0
mhc12 5 0 0.001 0.208 0.005 0.001 0.002 0 0.001 0.002 0 0.001 0.001 0
mhc13 5 0 0 0.898 0.002 0.003 0.003 0 0.003 0.003 0 0.003 0.003 0
mhc14 5 0.433 0.717 0.822 0 0 0 0 0 0 0 0 0 0

We can review the results regarding uniform/non-uniform DIF by looking at the chi* columns. Uniform DIF is indicated by column chi12 and non-uniform DIF by chi23, while column chi13 represents “an overall test of”total DIF effect” (Choi, Gibbons, and Crane 2011).

11 Item parameters

Code
Threshold 1 Threshold 2 Threshold 3 Threshold 4 Item location
mhc1 -2.36 -1.06 1.46 3.55 0.4
mhc4 0.25 0.45 2.07 3.20 1.49
mhc9 -1.06 -0.28 1.44 3.25 0.84
mhc10 -1.21 -0.54 1.27 2.70 0.55
mhc11 -1.54 -0.73 1.19 2.49 0.35
mhc12 -1.16 -0.39 1.51 2.48 0.61
mhc13 -0.99 -0.52 1.27 2.28 0.51
mhc14 -0.73 -0.03 1.12 1.82 0.55
Note:
Item location is the average of the thresholds for each item.

12 Transformation table

Code
RIscoreSE(df,score_range = c(-4,5))
Ordinal sum score Logit score Logit std.error
0 -4.000 1.386
1 -2.971 0.869
2 -2.404 0.689
3 -2.012 0.597
4 -1.705 0.540
5 -1.446 0.503
6 -1.217 0.476
7 -1.009 0.458
8 -0.814 0.444
9 -0.628 0.435
10 -0.447 0.428
11 -0.270 0.424
12 -0.095 0.422
13 0.079 0.420
14 0.254 0.420
15 0.429 0.421
16 0.606 0.422
17 0.784 0.424
18 0.963 0.426
19 1.145 0.430
20 1.328 0.434
21 1.516 0.439
22 1.707 0.445
23 1.905 0.454
24 2.111 0.466
25 2.329 0.481
26 2.563 0.502
27 2.820 0.530
28 3.109 0.569
29 3.450 0.626
30 3.877 0.718
31 4.480 0.898
32 5.000 1.113

13 Ordinal/interval figure

Code
RIscoreSE(df, output = "figure", score_range = c(-4,5))

14 Software used

Code
pkgs <- cite_packages(cite.tidyverse = TRUE, 
                      output = "table",
                      bib.file = "grateful-refs.bib",
                      include.RStudio = TRUE,
                      out.dir = getwd())
WARNING: One or more problems were discovered while enumerating dependencies.

# /Users/magnuspjo/Documents/Hub/rasch_samc_mhcsf/analysis2.qmd --------------
Error: <text>:213:34: unexpected ')'
212: df <- df %>%
213:   filter(50-rowSums(is.na(.)) >= )
                                      ^

Please see `?renv::dependencies` for more information.
Code
formattable(pkgs, 
            table.attr = 'class=\"table table-striped\" style="font-size: 15px; font-family: Lato; width: 80%"')
Package Version Citation
base 4.3.3 R Core Team (2024)
car 3.1.2 Fox and Weisberg (2019)
eRm 1.0.6 Mair and Hatzinger (2007b); Mair and Hatzinger (2007a); Hatzinger and Rusch (2009); Rusch, Maier, and Hatzinger (2013); Koller, Maier, and Hatzinger (2015); Debelak and Koller (2019)
foreach 1.5.2 Microsoft and Weston (2022)
formattable 0.2.1 Ren and Russell (2021)
furrr 0.3.1 Vaughan and Dancho (2022)
ggrepel 0.9.5 Slowikowski (2024)
glue 1.7.0 Hester and Bryan (2024)
kableExtra 1.4.0 Zhu (2024)
knitr 1.45 Xie (2014); Xie (2015); Xie (2023)
lordif 0.3.3 Choi, Laura E. Gibbons, and Crane (2016)
matrixStats 1.2.0 Bengtsson (2023)
mirt 1.41 Chalmers (2012)
patchwork 1.2.0 Pedersen (2024)
PerFit 1.4.6 Tendeiro, Meijer, and Niessen (2016)
psych 2.4.3 William Revelle (2024)
psychotree 0.16.1 Trepte and Verbeet (2010); Strobl, Wickelmaier, and Zeileis (2011); Strobl, Kopf, and Zeileis (2015); Komboz, Zeileis, and Strobl (2018); Wickelmaier and Zeileis (2018)
reshape 0.8.9 Wickham (2007)
RISEkbmRasch 0.1.33.5 Johansson (2024)
rmarkdown 2.26 Xie, Allaire, and Grolemund (2018); Xie, Dervieux, and Riederer (2020); Allaire et al. (2024)
TAM 4.2.21 @
tidyverse 2.0.0 Wickham et al. (2019)

15 References

Allaire, JJ, Yihui Xie, Christophe Dervieux, Jonathan McPherson, Javier Luraschi, Kevin Ushey, Aron Atkins, et al. 2024. rmarkdown: Dynamic Documents for r. https://github.com/rstudio/rmarkdown.
Bengtsson, Henrik. 2023. matrixStats: Functions That Apply to Rows and Columns of Matrices (and to Vectors). https://CRAN.R-project.org/package=matrixStats.
Chalmers, R. Philip. 2012. mirt: A Multidimensional Item Response Theory Package for the R Environment.” Journal of Statistical Software 48 (6): 1–29. https://doi.org/10.18637/jss.v048.i06.
Choi, Seung W., Laura E. Gibbons, and Paul K. Crane. 2011. “Lordif: An R Package for Detecting Differential Item Functioning Using Iterative Hybrid Ordinal Logistic Regression/Item Response Theory and Monte Carlo Simulations.” Journal of Statistical Software 39 (1): 1–30. https://doi.org/10.18637/jss.v039.i08.
Choi, Seung W., with contributions from Laura E. Gibbons, and Paul K. Crane. 2016. lordif: Logistic Ordinal Regression Differential Item Functioning Using IRT. https://CRAN.R-project.org/package=lordif.
Debelak, Rudolf, and Ingrid Koller. 2019. “Testing the Local Independence Assumption of the Rasch Model with Q3-Based Nonparametric Model Tests.” Applied Psychological Measurement 44. https://doi.org/10.1177/0146621619835501.
Echeverría, Guadalupe, Manuel Torres-Sahli, Nuria Pedrals, Oslando Padilla, Attilio Rigotti, and Marcela Bitran. 2017. “Validation of a Spanish Version of the Mental Health Continuum-Short Form Questionnaire.” Psicothema 29 (February): 96–102. https://doi.org/10.7334/psicothema2016.3.
———. n.d. “Data, Instrument and Code for Validation of s-MHC-SF.” https://doi.org/10.6084/m9.figshare.3370828.v1.
Fox, John, and Sanford Weisberg. 2019. An R Companion to Applied Regression. Third. Thousand Oaks CA: Sage. https://socialsciences.mcmaster.ca/jfox/Books/Companion/.
Hatzinger, Reinhold, and Thomas Rusch. 2009. “IRT Models with Relaxed Assumptions in eRm: A Manual-Like Instruction.” Psychology Science Quarterly 51.
Hester, Jim, and Jennifer Bryan. 2024. glue: Interpreted String Literals. https://CRAN.R-project.org/package=glue.
Johansson, Magnus. 2024. RISEkbmRasch: Psychometric Analysis in r with Rasch Measurement Theory. https://github.com/pgmj/RISEkbmRasch.
Koller, Ingrid, Marco Maier, and Reinhold Hatzinger. 2015. “An Empirical Power Analysis of Quasi-Exact Tests for the Rasch Model: Measurement Invariance in Small Samples.” Methodology 11. https://doi.org/10.1027/1614-2241/a000090.
Komboz, Basil, Achim Zeileis, and Carolin Strobl. 2018. “Tree-Based Global Model Tests for Polytomous Rasch Models.” Educational and Psychological Measurement 78 (1): 128–66. https://doi.org/10.1177/0013164416664394.
Mair, Patrick, and Reinhold Hatzinger. 2007a. “CML Based Estimation of Extended Rasch Models with the eRm Package in r.” Psychology Science 49. https://doi.org/10.18637/jss.v020.i09.
———. 2007b. “Extended Rasch Modeling: The eRm Package for the Application of IRT Models in r.” Journal of Statistical Software 20. https://doi.org/10.18637/jss.v020.i09.
Microsoft, and Steve Weston. 2022. foreach: Provides Foreach Looping Construct. https://CRAN.R-project.org/package=foreach.
Pedersen, Thomas Lin. 2024. patchwork: The Composer of Plots. https://CRAN.R-project.org/package=patchwork.
R Core Team. 2024. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
Ren, Kun, and Kenton Russell. 2021. formattable: Create Formattable Data Structures. https://CRAN.R-project.org/package=formattable.
Rusch, Thomas, Marco Maier, and Reinhold Hatzinger. 2013. “Linear Logistic Models with Relaxed Assumptions in r.” In Algorithms from and for Nature and Life, edited by Berthold Lausen, Dirk van den Poel, and Alfred Ultsch. Studies in Classification, Data Analysis, and Knowledge Organization. New York: Springer. https://doi.org/10.1007/978-3-319-00035-0_34.
Slowikowski, Kamil. 2024. ggrepel: Automatically Position Non-Overlapping Text Labels with ggplot2. https://CRAN.R-project.org/package=ggrepel.
Strobl, Carolin, Julia Kopf, and Achim Zeileis. 2015. “Rasch Trees: A New Method for Detecting Differential Item Functioning in the Rasch Model.” Psychometrika 80 (2): 289–316. https://doi.org/10.1007/s11336-013-9388-3.
Strobl, Carolin, Florian Wickelmaier, and Achim Zeileis. 2011. “Accounting for Individual Differences in Bradley-Terry Models by Means of Recursive Partitioning.” Journal of Educational and Behavioral Statistics 36 (2): 135–53. https://doi.org/10.3102/1076998609359791.
Tendeiro, Jorge N., Rob R. Meijer, and A. Susan M. Niessen. 2016. PerFit: An R Package for Person-Fit Analysis in IRT.” Journal of Statistical Software 74 (5): 1–27. https://doi.org/10.18637/jss.v074.i05.
Trepte, Sabine, and Markus Verbeet, eds. 2010. Allgemeinbildung in Deutschland – Erkenntnisse Aus Dem SPIEGEL Studentenpisa-Test. Wiesbaden: VS Verlag.
Vaughan, Davis, and Matt Dancho. 2022. furrr: Apply Mapping Functions in Parallel Using Futures. https://CRAN.R-project.org/package=furrr.
Wickelmaier, Florian, and Achim Zeileis. 2018. “Using Recursive Partitioning to Account for Parameter Heterogeneity in Multinomial Processing Tree Models.” Behavior Research Methods 50 (3): 1217–33. https://doi.org/10.3758/s13428-017-0937-z.
Wickham, Hadley. 2007. “Reshaping Data with the Reshape Package.” Journal of Statistical Software 21 (12). https://www.jstatsoft.org/v21/i12/.
Wickham, Hadley, Mara Averick, Jennifer Bryan, Winston Chang, Lucy D’Agostino McGowan, Romain François, Garrett Grolemund, et al. 2019. “Welcome to the tidyverse.” Journal of Open Source Software 4 (43): 1686. https://doi.org/10.21105/joss.01686.
William Revelle. 2024. psych: Procedures for Psychological, Psychometric, and Personality Research. Evanston, Illinois: Northwestern University. https://CRAN.R-project.org/package=psych.
Xie, Yihui. 2014. knitr: A Comprehensive Tool for Reproducible Research in R.” In Implementing Reproducible Computational Research, edited by Victoria Stodden, Friedrich Leisch, and Roger D. Peng. Chapman; Hall/CRC.
———. 2015. Dynamic Documents with R and Knitr. 2nd ed. Boca Raton, Florida: Chapman; Hall/CRC. https://yihui.org/knitr/.
———. 2023. knitr: A General-Purpose Package for Dynamic Report Generation in r. https://yihui.org/knitr/.
Xie, Yihui, J. J. Allaire, and Garrett Grolemund. 2018. R Markdown: The Definitive Guide. Boca Raton, Florida: Chapman; Hall/CRC. https://bookdown.org/yihui/rmarkdown.
Xie, Yihui, Christophe Dervieux, and Emily Riederer. 2020. R Markdown Cookbook. Boca Raton, Florida: Chapman; Hall/CRC. https://bookdown.org/yihui/rmarkdown-cookbook.
Zhu, Hao. 2024. kableExtra: Construct Complex Table with kable and Pipe Syntax. https://CRAN.R-project.org/package=kableExtra.

Reuse